using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;
using EnterpriseDT.Net.Ftp;

namespace PicturePage
{
    class Utility
    {
        /// <summary>
        /// Encrypts the password
        /// </summary>
        /// <param name="ftpPassword">Password to Encrypt</param>
        /// <param name="password">The password</param>
        /// <returns></returns>
        public static string EncryptMessage(string ftpPassword, string password)
        {
            TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
            des.IV = new byte[8];

            PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, new byte[0]);
            des.Key = pdb.CryptDeriveKey("RC2", "MD5", 128, new byte[8]);
            
            MemoryStream ms = new MemoryStream(ftpPassword.Length * 2);
            CryptoStream encStream = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);

            byte[] plainBytes = Encoding.UTF8.GetBytes(ftpPassword);
            encStream.Write(plainBytes, 0, plainBytes.Length);
            encStream.FlushFinalBlock();
            
            byte[] encryptedBytes = new byte[ms.Length];
            ms.Position = 0;
            ms.Read(encryptedBytes, 0, (int)ms.Length);
            encStream.Close();
            
            return Convert.ToBase64String(encryptedBytes);
        }

        /// <summary>
        /// Decrypts the password
        /// </summary>
        /// <param name="encryptedBase64">Encrypted password</param>
        /// <param name="password">The password</param>
        /// <returns></returns>
        public static string DecryptMessage(string encryptedBase64, string password)
        {
            try
            {
                TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
                des.IV = new byte[8];

                PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, new byte[0]);
                des.Key = pdb.CryptDeriveKey("RC2", "MD5", 128, new byte[8]);

                byte[] encryptedBytes = Convert.FromBase64String(encryptedBase64);
                MemoryStream ms = new MemoryStream(encryptedBase64.Length);
                CryptoStream decStream = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
                decStream.Write(encryptedBytes, 0, encryptedBytes.Length);
                decStream.FlushFinalBlock();

                byte[] plainBytes = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(plainBytes, 0, (int)ms.Length);
                decStream.Close();
                return Encoding.UTF8.GetString(plainBytes);
            }
            catch (Exception ex)
            {
                throw new Exception("Could not Decrypt the Password", ex);
            }
        }

        /// <summary>
        /// Sets up the FTP Settings from an external file
        /// </summary>
        public static bool SetupSettings(string filename, ref Configuration config, FTPConnection ftpConnection)
        {
            if (File.Exists(filename))
            {
                if (!config.SettingsLoaded)
                {
                    config = Configuration.Deserialize("config.xml");
                    config.SettingsLoaded = true;
                    if (config.ConfigPassword != "SomeStringThatNoOneWillEverUseDefault")
                    {
                        //create a popup box that inputs a password...
                        PopupBox popupBox = new PopupBox();
                        popupBox.StartPosition = FormStartPosition.CenterScreen;
                        int tries = 3;
                        while (tries >= 0)
                        {
                            config.ConfigPassword = popupBox.ShowInputBox("Input Password", "Please Input your Password.");

                            //if they cancelled to closed the password window...
                            if (config.ConfigPassword == "SomeStringThatNoOneWillEverUse") { break; }

                            try
                            {
                                ftpConnection.ServerAddress = config.GetDecryptedServerAddress();
                                ftpConnection.ServerPort = config.GetDecryptedServerPort();
                                ftpConnection.UserName = config.GetDecryptedUserName();
                                ftpConnection.Password = config.GetDecryptedPassword();

                                MessageBox.Show("Password Correct!", "FTP Password", MessageBoxButtons.OK);
                                return true;
                            }
                            catch
                            {
                                MessageBox.Show("Password was not Correct!\r\n" + tries.ToString() + " attempts left", "FTP Password", MessageBoxButtons.OK);
                            }
                            tries--;
                        }
                    }
                }
                return false;
            }
            else
            {
                MessageBox.Show("No FTP Settings were found!", "No FTP Settings", MessageBoxButtons.OK);
                return false;
            }
        }

        /// <summary>
        /// Connects to the ftp server if it needs to
        /// </summary>
        public static bool ConnectToFTP(FTPConnection ftpConnection, Configuration config)
        {
            //only make a new connection if there isn't already a connection
            if (!ftpConnection.IsConnected)
            {
                try
                {
                    ftpConnection.ServerAddress = config.GetDecryptedServerAddress();
                    ftpConnection.ServerPort = config.GetDecryptedServerPort();
                    ftpConnection.UserName = config.GetDecryptedUserName();
                    ftpConnection.Password = config.GetDecryptedPassword();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("There is an Error with your FTP settings.\r\n" + ex, "FTP Settings Error", MessageBoxButtons.OK);
                    return false;
                }

                ftpConnection.Protocol = FileTransferProtocol.FTP;
                try
                {
                    ftpConnection.Connect();
                    return true;
                }
                catch
                {
                    MessageBox.Show("Error connecting to the FTP Server.\r\nCheck your FTP settings.", "FTP Login Error", MessageBoxButtons.OK);
                    return false;
                }
            }
            return false;
        }


        /// <summary>
        /// Creates a directory on the ftp if it is needed
        /// </summary>
        /// <param name="directory"></param>
        /// <param name="ftpConnection"></param>
        public static void CreateDirectory(string directory, FTPConnection ftpConnection)
        {
            string[] dir = directory.Split('/');
            string directoryToCheck = "";
            foreach (string checkDir in dir)
            {
                try
                {
                    bool createDirectory = true; //tells us if we need to create the directory
                    string[] ftpFiles = ftpConnection.GetFiles(directoryToCheck); //need all the files in that folder first
                    directoryToCheck += checkDir; //add the directory we are checking
                    foreach (string ftpFile in ftpFiles)
                    {
                        //if we find a match then we don't need to create the directory
                        if (ftpFile == directoryToCheck)
                        {
                            createDirectory = false;
                        }
                    }
                    directoryToCheck += "/"; //need to append this so the directory will get created properly
                    if (createDirectory)
                        ftpConnection.CreateDirectory(directoryToCheck); //create the directory
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }
    }
}
